﻿Public Class ExceptionMaintenanceControl

    Private l_Maintenance As MaintenanceType
    Private l_IsNew As Boolean = False
    Private l_HashTable As New Dictionary(Of String, Object)
    'NOTE:  The HashTable is used to store the properties and property values of the object under management.
    '       The object could be a Loading Dock Exception or a Recurrance object.
    '       The HashTable allows for the rolling back of changes made in the detail form if the Cancel action is invoked.

    Public Enum MaintenanceType
        DockException = 0
        RecurrenceDockException = 1
    End Enum

    Public Sub New()
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.

        Me.DbiList2.TitleText = "Loading Docks Containing" & vbCrLf & _
                                "Exception(s)"
    End Sub

    Public Sub SetForm(ByVal Maintenance As MaintenanceType)
        'Called to set the local variables and populate the form with the type of exceptions being managed.
        l_Maintenance = Maintenance
        Me.DbiList1.Tag = Nothing
        PopulateForm()

    End Sub

    Public Sub DbiList1_NodeClick(ByVal sender As System.Object, ByVal e As Dbi.WinControl.NodeClickEventArgs) Handles DbiList1.NodeClick
        'This event is fired when an item in the Exceptions list receives a mouse click.
        'NOTE: The code allows for a left mouse click on any item or right mouse click on any unselected item.
        If e.Item IsNot Nothing Then

            If e.Button = Windows.Forms.MouseButtons.Left Or (e.Button = Windows.Forms.MouseButtons.Right And e.Item.Selected = False) Then
                'Store the selected item's tag value (the exception object) in the tag value of the dbiList control.
                Me.DbiList1.Tag = e.Item.Tag

                'Select the item if it is not already selected.
                e.Item.Selected = True

                'Get the loading docks associated with the exception and populate the Loading Docks list.
                PopulateLoadingDockList()

                'A default user control detail form is used to show the values of the properties of the current exception.
                'The current Exception (single or recurring) is stored in the Tag property of the dbiList for easy reference
                'in code. The Exception can be passed as well as the current global objWSFObject and the detail form will display
                'the exception's detail for editing or viewing.
                Me.DbiWSFObjectDetail1.DisplayObject(Me.DbiList1.Tag, myWSFObjects)

            End If

        End If

    End Sub

    Private Sub DocksOnException()
        'The following LINQ query will retrieve all of the LoadingDocks (stored in the Tag property of the dbiNodeItems in the
        ' second dbiList) that have their checkbox checked.
        Dim CheckedLINQ = From warehouse As Dbi.WinControl.dbiNodeItem In Me.DbiList2.Items _
                          From loadingDock As Dbi.WinControl.dbiNodeItem In warehouse.Items _
                          Where loadingDock.GetCellText(1).ToString = "1" _
                          Select loadingDock.Tag

        If Me.DbiList1.Tag IsNot Nothing Then

            If CheckedLINQ.Count > 0 Then

                'Retrieve the LoadingDockID's from the LoadingDocks retrieved in the LINQ query.
                'This will allow the update of the sub-table linking the Exception with the LoadingDocks it affects.

                'Iterate through the collection retrieved from the LINQ statement.
                Dim LoadingDocks As New System.Collections.Generic.List(Of System.Guid)
                For Each curLoadingDock As dbiWSF.FrameworkObjects.objLoadingDock In CheckedLINQ
                    LoadingDocks.Add(curLoadingDock.LoadingDockID)
                Next

                'Check the type of the Current exception, and then trigger the appropriate method to
                'update the records in the sub-table to ensure the link between the Exception and the LoadingDock(s)
                'is stored properly.
                Select Case Me.DbiList1.Tag.GetType.ToString
                    Case GetType(dbiWSF.FrameworkObjects.objLoadingDockException).ToString
                        Me.DbiList1.Tag.AddLoadingDocks(LoadingDocks)
                    Case GetType(dbiWSF.FrameworkObjects.objRecurrence).ToString
                        Me.DbiList1.Tag.AddRecurrenceObjects(LoadingDocks)
                End Select

            Else

                'NOTE: The framework supports the existence of exceptions that are not attached to any loading docks.
                'If there are no LoadingDock's affected by the Exception it will not be displayed inside any of the custom user
                'controls.  It will still exist in the LoadingDockException or Recurrence collection (respectively) of the objWSFObject.
                MessageBox.Show("The Exception you have created/modified will not appear inside the Schedule," + _
                "as it has not been assigned to any loading docks.", "There are no LoadingDocks associated with this Exception", _
                MessageBoxButtons.OK, MessageBoxIcon.Warning)

            End If

        End If

    End Sub

    Private Sub ToolStripEditException_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripEditException.Click
        'Set the properties of the selected exception and the affected LoadingDocks for editing by the user.
        Me.DbiList1.Enabled = False
        Me.DbiList2.Enabled = True
        Me.DbiWSFObjectDetail1.Enabled = True
        Me.ButtonSaveMaintenance.Enabled = True
        Me.ButtonCancelMaintenance.Enabled = True

        'Cancel or Save before navigating to another control/form in the application.
        MainForm.DbiExplorerBar1.Enabled = False
        MainForm.ToolStripHomeButton.Enabled = False

    End Sub

    Private Sub PopulateLoadingDockList()
        'Remove all items from the Loading Docks List
        Me.DbiList2.Items.Clear()

        'Loop through the collection of Warehouses found in the global objWSFObject.  Select all LoadingDocks
        'which are stored in a collection as a property on each Warehouse object.

        For Each Warehouse As dbiWSF.FrameworkObjects.objWarehouse In myWSFObjects.Warehouses
            'Create a dbiNodeItem as a header item to display information about each warehouse.
            Dim WareNode As New Dbi.WinControl.dbiNodeItem(Warehouse.Description)
            WareNode.Tag = Warehouse
            WareNode.Header = True

            'Loop through the collection of Loading Docks on each warehouse
            For Each LoadingDock As dbiWSF.FrameworkObjects.objLoadingDock In Warehouse.LoadingDocks
                'Create a dbiNodeItem to display information for each Loading Dock as a child under the Warehouse Header Node.
                Dim DockNode As New Dbi.WinControl.dbiNodeItem(LoadingDock.Description)

                If Me.DbiList1.Tag IsNot Nothing Then

                    'Test to see if the exception is a loading dock or recurrance object.
                    If l_Maintenance = MaintenanceType.DockException Then

                        'NOTE:  The current LoadingDockException is stored inside the Tag property of the dbiList control.
                        'The Exception properties such as its collection of LoadingDocks (a collection of System.GUID)
                        'can be used to determine if a LoadingDock is currently affected by the exception.

                        If Me.DbiList1.Tag.LoadingDocks.Contains(LoadingDock.LoadingDockID) Then
                            'Set the check box in the item appropriately
                            DockNode.Text += ";1"
                        End If

                    Else

                        'NOTE:  The current RecurrenceException is stored inside the Tag property of the dbiList control.
                        'The Exception properties such as its collection of LoadingDocks (a collection of System.GUID)
                        'can be used to determine if a LoadingDock is currently affected by the exception.

                        If Me.DbiList1.Tag.ObjectType = dbiWSF.FrameworkObjects.RecurrenceObjectType.DockException Then

                            If Me.DbiList1.Tag.RecurringObjects.Contains(LoadingDock.LoadingDockID) Then
                                'Set the check box in the item appropriately
                                DockNode.Text += ";1"
                            End If

                        End If

                    End If

                Else

                    'There is nothing to edit.
                    Me.DbiWSFObjectDetail1.Enabled = False

                End If

                'Store the LoadingDock object in the Tag of the dbiNodeItem in the Loading Docks list.
                DockNode.Tag = LoadingDock

                'Add the node to the parent Warehouse Node.
                WareNode.Items.Add(DockNode)

                'Expand all the child nodes (loading docks) under the parent node (warehouse).
                WareNode.ExpandAll()

            Next

            'Add the Warehouse node to the Loading Docks dbiList control.
            Me.DbiList2.Items.Add(WareNode)

        Next

    End Sub

    Private Sub PopulateForm()
        'Retrieve the appropriate kind of exception (loading dock or reoccurring) and populate the control.

        'Clear the items out of the Exceptions List.
        Me.DbiList1.Items.Clear()

        'Loop through either the LoadingDockException or Recurrence collections on the global objWSFObject
        'and populate the Exceptions list with dbiNodeItems based on the objects it finds in the respective collection.

        Select Case l_Maintenance
            Case MaintenanceType.DockException

                Me.DbiList1.TitleText = "LoadingDock Exceptions"

                For Each DockException As dbiWSF.FrameworkObjects.objLoadingDockException In myWSFObjects.LoadingDockExceptions

                    'Create a new dbiList node item to represent the exception.
                    Dim ExceptionNode As New Dbi.WinControl.dbiNodeItem(DockException.Description)

                    'Store the exception object from the dbiWSF in the tag property of the node item.
                    ExceptionNode.Tag = DockException

                    'Add the node item to the Exceptions List items collection.
                    Me.DbiList1.Items.Add(ExceptionNode)

                Next

            Case MaintenanceType.RecurrenceDockException

                Me.DbiList1.TitleText = "Recurring Exceptions"

                For Each RecurringDockException As dbiWSF.FrameworkObjects.objRecurrence In myWSFObjects.Recurrences

                    'Create a new dbiList node item to represent the exception.
                    Dim ExceptionNode As New Dbi.WinControl.dbiNodeItem(RecurringDockException.Description)

                    'Store the exception object from the dbiWSF in the tag property of the node item.
                    ExceptionNode.Tag = RecurringDockException

                    'Add the node item to the Exceptions List items collection.
                    Me.DbiList1.Items.Add(ExceptionNode)

                Next

        End Select

        Dim e2Send As New System.EventArgs

        Me.ButtonCancelMaintenance_Click(Me, e2Send)

        'Default the focus to the Exceptions List.
        Me.DbiList1.Select()

    End Sub

    Private Sub ToolStripAddNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripAddNew.Click

        'Create a new LoadingDockException or Recurrence object and set the form into edit mode.

        Select Case l_Maintenance
            Case MaintenanceType.DockException
                'Create a new Loading Dock Exception
                Dim newException As New dbiWSF.FrameworkObjects.objLoadingDockException(myWSFObjects)

                'Default the start date to today at the current time.
                newException.StartDate = Now

                'Default the end date to today at the current time plus one hour.
                newException.EndDate = Now.AddHours(1)

                'Call the ojbect's AddNew method to add it to the dbiWSF exception objects collection.
                newException.AddNew()

                'Store the new exception object in the tag property of the Exceptions List.
                'NOTE: This allows the object to be accessed at any time by any of the other controls on the form.
                Me.DbiList1.Tag = newException

                'Set the detail control to display the new exception's details.
                Me.DbiWSFObjectDetail1.DisplayObject(newException, myWSFObjects)

            Case MaintenanceType.RecurrenceDockException
                'Create a new Recurrance object
                Dim newException As New dbiWSF.FrameworkObjects.objRecurrence(myWSFObjects)

                'Default the start date to today at the current time.
                newException.ObjectStartDate = Now

                'Default the end date to today at the current time plus one hour.
                newException.ObjectEndDate = Now.AddHours(1)

                'Set the exceptino to be reoccurring
                newException.ObjectType = dbiWSF.FrameworkObjects.RecurrenceObjectType.DockException

                'Set the reoccurrance pattern to every 7 days starting today.
                newException.RecurringStartDate = Now.AddHours(-1)
                newException.RecurringEndDate = newException.RecurringStartDate.AddDays(7)

                'Call the ojbect's AddNew method to add it to the dbiWSF exception objects collection.
                newException.AddNew()

                'Store the new exception object in the tag property of the Exceptions List.
                'NOTE: This allows the object to be accessed at any time by any of the other controls on the form.
                Me.DbiList1.Tag = newException

                'Set the detail control to display the new exception's details.
                Me.DbiWSFObjectDetail1.DisplayObject(newException, myWSFObjects)

        End Select

        'Set the form to the new state.
        l_IsNew = True

        'Load the Loading Docks list with all the loading docks eligible for the exception.
        PopulateLoadingDockList()

        'Put the detail control into edit mode.
        ToolStripEditException_Click(sender, e)

    End Sub

    Private Sub ToolStripDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripDelete.Click

        If Me.DbiList1.Tag IsNot Nothing Then

            Select Case Me.DbiList1.Tag.GetType.ToString
                Case GetType(dbiWSF.FrameworkObjects.objLoadingDockException).ToString

                    'Clears the database of records in a sub-table linking the Exception to the LoadingDocks
                    Me.DbiList1.Tag.ClearLoadingDocks()

                Case GetType(dbiWSF.FrameworkObjects.objRecurrence).ToString

                    'Clears the database of records in a sub-table linking the recurring Exception to the LoadingDocks
                    Me.DbiList1.Tag.ClearObjects()

            End Select

            'Delete the object from the database and the dbiWSFObjects object.
            'NOTE:  The object in the tag can be a Loading Dock Exception or a Recurrance object.  
            '       Both have a remove method.
            '       The Remove Method takes the dbiWSFObjects object as a parameter in order to remove the
            '       exception from the object collection and the database.
            Me.DbiList1.Tag.remove(myWSFObjects)

            'Reset the form
            PopulateForm()

        End If

        'Clear out the controls in the detail control.
        Me.DbiWSFObjectDetail1.Controls.Clear()

    End Sub

    Private Sub ButtonSaveMaintenance_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSaveMaintenance.Click
        Try
            'Cache the original property values, in case there is an error and the values must be reset
            CacheProperties()

        Catch ex As Exception
            Throw New Exception("Error caching properties") '<Generic Error> Modify as needed
        End Try

        Try

            'Iterate through the controls in the detail control and update the object's properties with the values
            For Each curControl In Me.DbiWSFObjectDetail1.Controls

                If curControl.Tag IsNot Nothing Then

                    'Loop through each control in the detail user control.
                    'Apply the control's value to the corresponding property of the object used to create the instance
                    'of the user control.
                    'NOTE:  The label on the control reflects to the property on the object.
                    Dim curCol As DataColumn = curControl.Tag.ActualDataColumn
                    Dim curVal As Object = GetValue(curControl)

                    If curVal IsNot Nothing Then

                        Try
                            Dim PropInfo As System.Reflection.PropertyInfo
                            PropInfo = Me.DbiList1.Tag.GetType.GetProperty(curControl.Tag.LabelString)
                            If Not PropInfo Is Nothing Then
                                PropInfo.SetValue(Me.DbiList1.Tag, curVal, Nothing)
                            End If

                        Catch ex As Exception
                            'Issue with property, may not exist or be an automation issue.
                        End Try

                    End If

                End If

            Next

            'Update the loading docks attached to the exception.
            DocksOnException()

            Dim AllowChange As Boolean = False
            'Use the BusinessRulesDialog to test the updated property values against all existing rules
            Dim brDialog As New dbiWSF.Dialogs.dlgBusinessRule(myBusinessRules)
            brDialog.StartProcessSynch(Me.DbiList1.Tag, dbiWSF.BusinessRulesAndSupport.BusinessRuleObjects.RequestAction.Change)
            AllowChange = brDialog.Allow

            'Close the business rules dialog.
            brDialog.Dispose()

            'If the object passes the rules force an update to the data layer.
            'If the object fails the rules reset the values to their original values.
            If AllowChange Then
                'Cause the changes to be reflected in the database.
                UpdateData()
            Else
                'Discard the changes.
                ResetProperties()
            End If

        Catch ex As Exception
            Throw New Exception("Error Updating Form Data", ex) '<Generic Error>
        End Try

        'Reset the user control to its state before the editing began.
        Me.DbiList1.Enabled = True
        Me.DbiList2.Enabled = False
        Me.DbiWSFObjectDetail1.Enabled = False
        Me.DbiWSFObjectDetail1.DisplayObject(Me.DbiList1.Tag, myWSFObjects)
        Me.ButtonSaveMaintenance.Enabled = False
        Me.ButtonCancelMaintenance.Enabled = False

        'Re-enable the explorer bar and home button when the edit is complete.
        MainForm.DbiExplorerBar1.Enabled = True
        MainForm.ToolStripHomeButton.Enabled = True

        'If a new Exception was created synchronize the interface with the recently created object
        If l_IsNew Then

            'Reset the is is new flag.
            l_IsNew = False
            'Create a new node item in the Exceptions List.
            Dim newNode As New Dbi.WinControl.dbiNodeItem()
            newNode.Text = Me.DbiList1.Tag.Description
            newNode.Tag = Me.DbiList1.Tag
            Me.DbiList1.Items.Add(newNode)

            'Select the new item in the Exceptions List.
            Dim args As New Dbi.WinControl.NodeClickEventArgs
            args.Item = newNode
            args.Column = 0
            args.Button = Windows.Forms.MouseButtons.Left
            Me.DbiList1_NodeClick(Me.DbiList1, args)

        End If

    End Sub

    Private Sub CacheProperties()
        'This method will cache the current values of all the properties of the current exception being modified.
        'This allows for acess to the properties in the event of a cancel.
        l_HashTable.Clear()
        Dim MainPropInfo As System.Reflection.PropertyInfo

        For Each MainPropInfo In Me.DbiList1.Tag.GetType.GetProperties
            l_HashTable.Add(MainPropInfo.Name, MainPropInfo.GetValue(Me.DbiList1.Tag, Nothing))
        Next

    End Sub

    Private Sub ResetProperties()
        'This method will reset the values of the current object's properties to their original values.
        'This is used if the changes made by the user need to be rolled back.
        Dim PropInfo As System.Reflection.PropertyInfo

        For Each HashVal As KeyValuePair(Of String, Object) In l_HashTable

            PropInfo = Me.DbiList1.Tag.GetType.GetProperty(HashVal.Key)
            PropInfo.SetValue(Me.DbiList1.Tag, HashVal.Value, Nothing)

        Next

    End Sub

    Private Sub UpdateData()
        'Loop through each of the controls on the ObjectDetail user control and update the AttachedDataRow of the current object.
        'Trigger a manual update of the data, back to the database.

        Try
            For Each curControl In Me.DbiWSFObjectDetail1.Controls

                If curControl.Tag IsNot Nothing Then

                    Dim curCol As DataColumn = curControl.Tag.ActualDataColumn
                    Dim curVal As Object = GetValue(curControl)

                    If curVal IsNot Nothing Then

                        Try
                            Me.DbiList1.Tag.AttachedDataRow.Item(curCol) = curVal

                        Catch ex As Exception
                            'Issue with property, may not exist or be an automation issue.

                        End Try

                    End If

                End If

            Next

            'Update of the database using the WSFDatabinding object on the global objWSFObject
            myWSFObjects.WSFDatabinding.ManualUpdateDatabases()

        Catch ex As Exception
            Throw New Exception("Error Saving Form Data", ex) '<Generic Error>
        End Try

    End Sub

    Private Function GetValue(ByRef ControlToParse As Object) As Object
        'Return the value from the auto-generated control on the ObjectDetail form.
        'The case statement will verify the type of the control, and retrieve the value from the correct property.
        'If a control is found that is not in the case statement, a value of "nothing" is returned
        Dim returnObject As Object
        Select Case ControlToParse.GetType.ToString
            Case GetType(Windows.Forms.TextBox).ToString
                If ControlToParse.ReadOnly = True Then
                    returnObject = New System.Guid(ControlToParse.Text.ToString)
                Else
                    returnObject = ControlToParse.Text
                End If

            Case GetType(Windows.Forms.NumericUpDown).ToString
                returnObject = CInt(ControlToParse.Value)
            Case GetType(dbiWSF.ControlLibrary.dbiDateTime).ToString
                returnObject = ControlToParse.DateTimeValue
            Case GetType(Windows.Forms.MaskedTextBox).ToString
                returnObject = CDec(ControlToParse.Text)
            Case GetType(Windows.Forms.ComboBox).ToString
                returnObject = ControlToParse.SelectedValue
            Case GetType(dbiWSF.ControlLibrary.RecurrenceDaysOfWeek).ToString
                returnObject = ControlToParse.DaysOfWeek
            Case Else
                returnObject = Nothing
        End Select

        Return returnObject

    End Function

    Private Sub ButtonCancelMaintenance_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCancelMaintenance.Click
        'Cancels out of the Edit or Addition of an item, resetting the form to its original status
        Me.DbiList1.Enabled = True
        Me.DbiList2.Enabled = False
        Me.DbiWSFObjectDetail1.Enabled = False
        Me.ButtonSaveMaintenance.Enabled = False
        Me.ButtonCancelMaintenance.Enabled = False

        If l_IsNew Then

            'Take the form out of "New" mode.
            l_IsNew = False

            'NOTE:  The object in the tag can be a Loading Dock Exception or a Recurrance object.  
            '       Both have a remove method.
            Me.DbiList1.Tag.remove(myWSFObjects)

            'Clear the controls in the detail control.
            Me.DbiWSFObjectDetail1.Controls.Clear()

            Me.DbiList1.Tag = Nothing

        End If

        'Re-enable the explorer bar and home button when the edit is complete.
        MainForm.DbiExplorerBar1.Enabled = True
        MainForm.ToolStripHomeButton.Enabled = True

    End Sub

    Public Sub ClearForm()
        'Clear the controls from the detail control.
        Me.DbiWSFObjectDetail1.Controls.Clear()

        'Clear the items from the Loading Docks list.
        Me.DbiList2.Items.Clear()

    End Sub

    Private Sub DbiList2_FirstDraw(ByVal sender As Object, ByVal e As System.EventArgs) Handles DbiList2.FirstDraw
        Dim DbiColumnItem5 As Dbi.WinControl.dbiColumnItem = New Dbi.WinControl.dbiColumnItem
        Dim DbiColumnItem6 As Dbi.WinControl.dbiColumnItem = New Dbi.WinControl.dbiColumnItem

        DbiColumnItem5.BackColor = System.Drawing.Color.Empty
        DbiColumnItem5.BackColorTo = System.Drawing.Color.Empty
        DbiColumnItem5.ForeColor = System.Drawing.Color.Empty
        DbiColumnItem5.Format.BackColor = System.Drawing.Color.Empty
        DbiColumnItem5.Format.BackColorTo = System.Drawing.Color.Empty
        DbiColumnItem5.Format.ForeColor = System.Drawing.Color.Empty
        DbiColumnItem5.Text = "Loading Dock"
        DbiColumnItem5.Width = 180
        DbiColumnItem6.BackColor = System.Drawing.Color.Empty
        DbiColumnItem6.BackColorTo = System.Drawing.Color.Empty
        DbiColumnItem6.DataType = Dbi.WinControl.enumDataType.[Boolean]
        DbiColumnItem6.ForeColor = System.Drawing.Color.Empty
        DbiColumnItem6.Format.BackColor = System.Drawing.Color.Empty
        DbiColumnItem6.Format.BackColorTo = System.Drawing.Color.Empty
        DbiColumnItem6.Format.CheckBox = Dbi.enumCheckBox.Standard
        DbiColumnItem6.Format.ForeColor = System.Drawing.Color.Empty
        DbiColumnItem6.Text = ""
        DbiColumnItem6.Width = 22

        Me.DbiList2.Columns.Add(DbiColumnItem5)
        Me.DbiList2.Columns.Add(DbiColumnItem6)

    End Sub
End Class
